package com.heima.user.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.vos.UserVo;
import com.heima.user.listen.CommonListen;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.ApUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {
    @Autowired
    private ApUserMapper apUserMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 批量导入APP用户信息
     * @param file
     */
    @Override
    public ResponseResult importUser(MultipartFile file) throws IOException {
        // 每隔1000条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
        final int BATCH_COUNT = 1000;
        CommonListen<ApUser> commonListen = new CommonListen<>();
        EasyExcel.read(file.getInputStream(), ApUser.class, commonListen).sheet(0).doRead();
        // 获取导入的数据集合
        List<ApUser> apUserList = commonListen.getList();
        // 去重
        Set<String> phoneSet = new HashSet<>();
        // 从数据库中查询所有的用户信息
        apUserMapper.selectList(null).forEach(apUser -> {
            // 将数据库中的用户信息放入set集合中
            phoneSet.add(apUser.getPhone());
        });
        List<ApUser> newApUserList = new ArrayList<>(); // 去重后的数据
        List<ApUser> repeatList = new ArrayList<>(); // 重复的数据
        for (ApUser apUser : apUserList) {
            String userPhone = apUser.getPhone();
            if (!phoneSet.contains(userPhone)) {
                // set中不包含重复的 添加到未重复的集合 后续插入数据库
                phoneSet.add(userPhone);
                newApUserList.add(apUser);
            }else {
                // set中包含重复的 添加到重复数据集合 后续插入redis
                repeatList.add(apUser);
            }
        }
        List<ApUser> list = new ArrayList<>();
        for (ApUser apUser : newApUserList) {
            list.add(apUser);
            // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
            if (list.size() >= BATCH_COUNT) {
                // 存储数据库
                apUserMapper.insertBatch(list);
                // 清空list
                list.clear();
            }
        }
        // 如果list中还有数据，则需要存储到数据库中
        if (list.size() > 0) {
            apUserMapper.insertBatch(list);
        }
        // 将repeatList转成字符串对象
        String sList = JSONObject.toJSON(repeatList).toString();
        // 将重复的数据缓存到redis中 并设置失效时间1小时
        redisTemplate.opsForValue().set("repeatList", sList);
        redisTemplate.expire("repeatList", 1, TimeUnit.HOURS);
        // 前端提示
        UserVo userVo = new UserVo();
        userVo.setRepetitionNumber(repeatList.size());
        userVo.setSuccessNumber(newApUserList.size());
        userVo.setRepetitionId("repeatList");
        System.out.println(userVo);
        return ResponseResult.okResult(userVo);
    }

    /**
     * 下载重复的APP用户信息
     * @param repetitionId
     */
    @Override
    public void exportUser(String repetitionId) {
        // 将重复的数据从redis中取出
        String sList = (String) redisTemplate.opsForValue().get(repetitionId);
        // 将字符串对象转成list对象
        List<ApUser> repeatList = JSONObject.parseArray(sList, ApUser.class);
        // 将list转成excel对象
        EasyExcel.write(new File("D:\\repeat.xlsx"), ApUser.class).sheet("重复的用户").doWrite(repeatList);
    }
}